﻿using Microsoft.Extensions.Primitives;

namespace _02_Configuration
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var provider = new FileConfigurationProvider();
            //绑定
            provider.Watch();
            new TaskCompletionSource().Task.Wait();
        }
    }

    /// <summary>
    /// 文件配置程序超类
    /// </summary>
    public class FileConfigurationProvider
    {
        private CancellationTokenSource? tokenSource;

        public void Load()
        {
            Console.WriteLine($"[{DateTime.Now}]文件已加载...");
        }

        public void Watch()
        {
            //将changeToken生产者和changeToken消费者进行绑定(订阅)
            ChangeToken.OnChange(GetReloadToken, Load);
            //触发Change事件
            var t = new Thread(() =>
            {
                while (true)
                {
                    Thread.Sleep(3000);
                    var t = tokenSource;
                    tokenSource = null;
                    //注意，取消之前一定要将tokenSource设置成null，不然会引发堆栈异常
                    //因为通知了取消，就会获取changeChange，但是你没有设置成null，OnChange认为又发生了取消通知
                    //会一直循环
                    t!.Cancel();//发布
                }
            });
            t.Start();
        }

        /// <summary>
        /// 令牌生产者
        /// </summary>
        /// <returns></returns>
        public IChangeToken GetReloadToken()
        {
            lock (this)
            {
                //如果被消费就创建一个新的
                if (tokenSource == null)
                {
                    tokenSource = new CancellationTokenSource();
                }
                return new CancellationChangeToken(tokenSource.Token);
            }
        }

    }
}